/*
 * vrest.c
 * Copyright (C) Albert Aixendri 2010 <albertaixendri@gmail.com>
 * 
 * libvrest is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * libvrest is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "vrest.h"

static void *myrealloc(void *ptr, size_t size);

static void *myrealloc(void *ptr, size_t size)
{
  if(ptr)
    return realloc(ptr, size);
  else
    return malloc(size);
}

static size_t
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)data;

  mem->memory = myrealloc(mem->memory, mem->size + realsize + 1);
  if (mem->memory) {
    memcpy(&(mem->memory[mem->size]), ptr, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
  }
  return realsize;
}

int initHandle() {
	struct Handle *handle = malloc(sizeof(struct Handle));
	return (int)handle;
}

void doPostHandle(int ihandle, char *url, char *header, char *post) {
	struct Handle *handle = (struct Handle *) ihandle;
	handle->curl = curl_easy_init();

	curl_easy_setopt(handle->curl, CURLOPT_URL, url);

	struct curl_slist *lHeaders=NULL;
	lHeaders = curl_slist_append(lHeaders, header);
	curl_easy_setopt(handle->curl, CURLOPT_HTTPHEADER, lHeaders);

	char *newPost = malloc(strlen(post)+1);
	strcpy(newPost,post);
	curl_easy_setopt(handle->curl, CURLOPT_POSTFIELDS, newPost);

	struct MemoryStruct chunk;
	chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
	chunk.size = 0;    /* no data at this point */

	curl_easy_setopt(handle->curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

	curl_easy_setopt(handle->curl, CURLOPT_WRITEDATA, (void *)&chunk);

	//curl_easy_setopt(handle->curl, CURLOPT_VERBOSE, 1);

	curl_easy_setopt(handle->curl, CURLOPT_FOLLOWLOCATION, 1);

	struct MemoryStruct resheader;
	resheader.memory=NULL;
	resheader.size = 0; 
	curl_easy_setopt(handle->curl, CURLOPT_WRITEHEADER, (void *)&resheader);

	curl_easy_perform(handle->curl);

	handle->body = malloc(chunk.size + 1);
	strcpy(handle->body,chunk.memory);

	handle->header = malloc(resheader.size + 1);
	strcpy(handle->header,resheader.memory);

	curl_easy_cleanup(handle->curl);
}

void doGetHandle(int ihandle, char *url, char *header) {
	struct Handle *handle = (struct Handle *) ihandle;
	handle->curl = curl_easy_init();

	curl_easy_setopt(handle->curl, CURLOPT_URL, url);

	struct curl_slist *lHeaders=NULL;
	lHeaders = curl_slist_append(lHeaders, header);
	curl_easy_setopt(handle->curl, CURLOPT_HTTPHEADER, lHeaders);

	struct MemoryStruct chunk;
	chunk.memory=NULL; 
	chunk.size = 0;

	curl_easy_setopt(handle->curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

	curl_easy_setopt(handle->curl, CURLOPT_WRITEDATA, (void *)&chunk);

	//curl_easy_setopt(handle->curl, CURLOPT_VERBOSE, 1);

	curl_easy_setopt(handle->curl, CURLOPT_FOLLOWLOCATION, 1);

	struct MemoryStruct resheader;
	resheader.memory=NULL;
	resheader.size = 0; 
	curl_easy_setopt(handle->curl, CURLOPT_WRITEHEADER, (void *)&resheader);

	curl_easy_perform(handle->curl);

	handle->body = malloc(chunk.size + 1);
	strcpy(handle->body,chunk.memory);

	handle->header = malloc(resheader.size + 1);
	strcpy(handle->header,resheader.memory);

	curl_easy_cleanup(handle->curl);
}

char *getBody(int ihandle) {
	struct Handle *handle = (struct Handle*) ihandle;
	return handle->body;
}

char *getHeader(int ihandle) {
	struct Handle *handle = (struct Handle*) ihandle;
	return handle->header;
}

void freeHandle(int ihandle) {
	struct Handle *handle = (struct Handle*) ihandle;
	free(handle->body);
	free(handle->header);
	free(handle);
}


